package com.tanhua.server.interceptor;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.common.utils.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.concurrent.TimeUnit;

@ControllerAdvice // 响应通知注解
public class MyResponseBodyAdvice implements ResponseBodyAdvice {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Value("${tanhua.cache.enable}")
    private Boolean enable;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    // 这个方法返回true 才会调用下面的响应曾倩方法
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        // 开关处于开启状态  是get请求  包含了@Cache注解
        return enable && methodParameter.hasMethodAnnotation(GetMapping.class)
                && methodParameter.hasMethodAnnotation(Cache.class);
    }

    @Override
    /**     进行响应增强的方法
        * @param body                       响应体
    	* @param methodParameter
    	* @param mediaType
    	* @param aClass
    	* @param serverHttpRequest
    	* @param serverHttpResponse
        * @return 
        * @author Wenshengzhang
        * @date  
    */
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // 1. 判断响应体是否为空
        if (body == null){
            // 如果响应结果为空直接返回null
            return null;
        }

        try {
            // 2. 响应体以字符串形式返回
            String redisValue = null;
            if (body instanceof String){
                // 如果响应数据是字符串
                redisValue = (String)body;
            }else {
                // 如果不是 将响应体转换成json字符串
                redisValue = MAPPER.writeValueAsString(body);

            }

            // 3. 获取redis中数据的key值, 先将请求对象强转为ServletServerHttpRequest对象，在获取ServletRequest对象
            String redisKey = RedisCacheInterceptor.createRedisKey(
                    ((ServletServerHttpRequest) serverHttpRequest).getServletRequest());

            // 4. 获取方法上的Cache注解，注解里定义了缓存过期时间
            Cache cache = methodParameter.getMethodAnnotation(Cache.class);
            // 因为方法需要的参数是long类型
            Long time = Long.valueOf(cache.time());

            // 将数据缓存到redis中,缓存时间单位是秒
            redisTemplate.opsForValue().set(redisKey,redisValue,time, TimeUnit.SECONDS);

            System.out.println("数据存入到了redis中");
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 返回响应体
        return body;
    }
}
